In [1]:
import numpy as np
import holoviews as hv
import datashader as ds
from holoviews.operation.datashader import aggregate, shade, datashade
from holoviews.operation import decimate
hv.notebook_extension('bokeh')
HoloViewsJS, BokehJS successfully loaded in this cell.

Aggregation

In [3]:
import seaborn as sns
In [4]:
for palette, values in sns.palettes.SEABORN_PALETTES.items():
    hv.Cycle.default_cycles[palette] = values

Points

In [5]:
points = hv.Points(np.random.multivariate_normal((0,0), [[0.1, 0.1], [0.1, 1.0]], (1000000,)))
datashade(points) + decimate(points)
Out[5]:

Paths

In [6]:
def random_walk(n):
    # Constants
    f = filter_width = 5000 # momentum or smoothing parameter, for a moving average filter

    # filtered random walk
    xs = np.convolve(np.random.normal(0, 0.1, size=n), np.ones(f)/f).cumsum()
    ys = np.convolve(np.random.normal(0, 0.1, size=n), np.ones(f)/f).cumsum()

    # Add "mechanical" wobble on the x axis
    xs += 0.1*np.sin(0.1*np.array(range(n-1+f)))

    # Add "measurement" noise
    xs += np.random.normal(0, 0.005, size=n-1+f)
    ys += np.random.normal(0, 0.005, size=n-1+f)
    return np.column_stack([xs, ys])
In [7]:
%%opts GridImage [logz=True]
np.random.seed(1)
paths = hv.Path([random_walk(100000) for i in range(10)])
aggregate(paths, width=200, height=200)
Out[7]:

NdOverlay

In [8]:
def time_series(T = 1, N = 100, mu = 0.1, sigma = 0.01, S0 = 20):        
    dt = float(T)/N
    t = np.linspace(0, T, N)
    W = np.random.standard_normal(size = N) 
    W = np.cumsum(W)*np.sqrt(dt) ### standard brownian motion ###
    X = (mu-0.5*sigma**2)*t + sigma*W 
    S = S0*np.exp(X) ### geometric brownian motion ###
    return S
In [9]:
%%opts GridImage [width=600]
tseries = hv.NdOverlay({i: hv.Curve(time_series(N=10000, S0=20+np.random.rand()))
                        for i in range(100)})
aggregate(tseries)
Out[9]:

HoloMap

In [10]:
hmap = hv.HoloMap({i: hv.Points(np.random.multivariate_normal((i,i), [[0.1, 0.1], [0.1, 1.0]], (100000,)))
                   for i in range(3)})
aggregate(hmap, x_range=hmap.range('x'), y_range=hmap.range('y'))
Out[10]:

Categorical aggregations

In [11]:
def random_cov():
    A = np.random.randn(2,2)
    return np.dot(A, A.T)

overlay = hv.NdOverlay({i: hv.Points(np.random.multivariate_normal((i,i), random_cov(), (100000,)))
                        for i in range(3)}, kdims=['Distribution'])
hv.NdLayout(aggregate(overlay, aggregator=ds.count_cat('Distribution'), dynamic=False))
Out[11]:

Shading

In [12]:
from matplotlib.cm import hot
In [13]:
points = hv.Points(np.random.multivariate_normal((0,0), random_cov(), (100000,)))
datashade(points, cmap=hot)
Out[13]:
In [14]:
np.random.seed(1)
paths = hv.Path([random_walk(100000) for i in range(10)])
datashade(paths)
Out[14]:
In [15]:
overlay = hv.NdOverlay({i: hv.Points(np.random.multivariate_normal(np.random.randn(2), random_cov(), (100000,)))
                        for i in range(10)}, kdims=['Distribution'])
datashade(overlay, aggregator=ds.count_cat('Distribution'))
Out[15]:

Datetime Timeseries

Currently datashader does not natively support datetime(64) types, we can however convert to an integer representation and apply a custom formatter:

In [16]:
import pandas as pd
from bokeh.models import DatetimeTickFormatter

def apply_formatter(plot, element):
    plot.handles['xaxis'].formatter = DatetimeTickFormatter()
In [44]:
%%opts RGB [finalize_hooks=[apply_formatter] width=1200]

drange = pd.date_range(start="2014-01-01", end="2016-01-01", freq='1min')
dates = drange.values.astype('int64')/10**6 # Convert dates to ints
curve = hv.Curve((dates, time_series(N=len(dates), S0=20+np.random.rand())))
datashade(curve)
Out[44]:
In [ ]: